package com.lucene.demo;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FloatField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.lucene.bean.Book;
import com.lucene.dao.BookDao;
import com.lucene.dao.BookDaoImpl;

public class MyLucene {

	//#########################创建一个索引库############################
	@Test
	public void testCreateIndex() throws IOException
	{
		//从sql得到数据(也可以自己定义一些数据测试)
		BookDao bookDao= new BookDaoImpl();
		List<Book> bookList = bookDao.queryBookList();
		
			//创建文档对象
		ArrayList<Document> documentList = new ArrayList<>();
		
		//遍历从sql得到的数据
		for (Book book : bookList) {
		
			Document document = new Document();//一个document相当于一行记录
			//创建field
		/*	关于是否分词根据实际情况来决定
			比如根据商品的id进行查询,就不用分词,比如搜索书,就需要分词
			
			关于是否要索引
			一般都需要索引,重量,大小,价格,等都需要索引(根据实际情况决定)
			比如图片路径就不需要存储
			
			关于是否要存储
			要在页面展示的都需要存储,比如搜多书,书的价格,图片路径都需要,所有都需要存储
			但是一些过大的东西,比如商品的介绍,等,就不需要存储,可以根据id去sql再查询
			
			决定是否分词,是否索引,看new的对象,不知道可以百度
			比如分词用TextFieid不分词用StringStringField*/
			Field fieldid = new StringField("id", book.getId().toString(), Store.YES);// 不分词 要索引  要存储
			Field fieldname = new TextField("name", book.getName(), Store.YES);//要分词 要索引 要存储
			Field fieldprice = new FloatField("price", book.getPrice(), Store.YES);//数字类型的比较特殊：需要分词  要索引   要存储
			Field fieldpic = new StoredField("pic", book.getPic());// 不分词 不索引 要存储
			Field fielddescription = new TextField("description", book.getDescription(),Store.NO);//要分词  要索引  不存储
			
			//添加到document中
			document.add(fieldid);
			document.add(fieldname);
			document.add(fieldprice);
			document.add(fieldpic);
			document.add(fielddescription);
			//添加到document集合中
			documentList.add(document);
			
		}
		
		
		//分词
		//Analyzer analyzer = new StandardAnalyzer();
		//使用中文分词器
		Analyzer analyzer = new IKAnalyzer();
		
		
		
		//指定一个索引库(索引文件存放的位置)
		FSDirectory directory = FSDirectory.open(new File("F:\\index"));
		//写出类配置
		IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, analyzer);
		//写出类加载索引库和配置
		IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);
		//写出到本地磁盘
		indexWriter.addDocuments(documentList);
		//关流
		indexWriter.close();
		
	}
	
	
	//##################################搜索索引库#####################################
	@Test
	public void secrch() throws IOException
	{
		//指定索引库位置
		FSDirectory directory = FSDirectory.open(new File("F:\\index"));
		//创建流对象
		DirectoryReader reader = DirectoryReader.open(directory);
		//创建搜索器
		IndexSearcher searcher = new IndexSearcher(reader);
		
		
		//创建查询对象,参数1搜索域名字,参数2,自己指定的关键字
	//	TermQuery termQuery = new TermQuery(new Term("name","java"));
		//测试搜索描述,可以搜出数据但是不会显示描述,因为没有储存
		TermQuery termQuery2 = new TermQuery(new Term("description","作"));
		
		
		
		
		//执行搜索,参数1搜索的对象,参数2排名靠前,对多查询100条数据
		TopDocs topDocs = searcher.search(termQuery2, 100);
		
		//获取结果集
		System.out.println("查询的数量是:"+topDocs.totalHits);
		
		//遍历结果集
		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		
		for (ScoreDoc scoreDoc : scoreDocs) {
			int id = scoreDoc.doc;//当前文档id
			
			//根据id获取文档
			Document doc = searcher.doc(id);
			
			System.out.println("商品名:"+doc.get("name"));
			System.out.println("价格:"+doc.get("price"));
			System.out.println("描述:"+doc.get("description"));//由于描述没有储存(因为文件太大),所以可以通过内容搜索到,但是不会显示内容,要显示内容需要通过id再去sql查询
			
		}
		
	}
	
	
	
//############	删除索引 ######################
	
	public void deleteIndex() throws IOException
	{
		//----------------------------------------------------根据Term删除指定索引----------------------------------------------------
		IndexWriter indexWriter = getIndexWriter();
		//跟Them匹配的都会被删除
		indexWriter.deleteDocuments(new Term("neme","java"));
		//----------------------删除全部索引----------------------------------------------------
		//indexWriter.deleteAll();
		//关流
		indexWriter.close();
		
		
	}
	
	//######################更新索引############################
	//如果没有查询到更新的文档，直接添加文档。
	//如果查到了，先删除查询到的文档，再进行添加
public void updateIndex() throws IOException
{
	IndexWriter indexWriter = getIndexWriter();
	
	Document document = new Document();
	document.add(new TextField("name", "websocket",Store.YES));
	//执行更新操作
	indexWriter.updateDocument(new Term("name", "java"), document);//先查询,再更新
	//关闭流
	indexWriter.close();
	}

//测试中文分词器
@Test
public void testIKAnalyzer() throws IOException
{
	Analyzer analyzer = new IKAnalyzer();
	TokenStream tokenStream = analyzer.tokenStream("", "共产党是伟大的一个党");
	
	
	//3.指定一个引用   （指定 词的引用  或者 偏移量(用于显示从第几个字分割到第几个字)）
	 CharTermAttribute addAttribute = tokenStream.addAttribute(CharTermAttribute.class);
	//4.设置一个偏移量的引用
	 OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
	 
	 
	//5.调用tokenstream的rest方法 重置
	 tokenStream.reset();
	//6.通过wihle 循环 遍历单词列表
	while(tokenStream.incrementToken()){
		///打印
		System.out.println("start>>"+offsetAttribute.startOffset());
		System.out.println(addAttribute.toString());//打印单词
		System.out.println("end>>"+offsetAttribute.endOffset());
	}
	tokenStream.close();
	
	
	
}




	
// ##############获取indexwriter公共方法#########################
public IndexWriter getIndexWriter() throws IOException
{
	//指定索引库位置
	FSDirectory directory = FSDirectory.open(new File("F:\\index"));
	//写出类配置
	IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST,  new StandardAnalyzer() );
	//写出类加载索引库和配置
	return new IndexWriter(directory,indexWriterConfig);
	
	}

	
	
	
}
